/* 
 * File:   secd.h
 * Author: Administrator
 *
 * Created on 2016年9月6日, 下午11:32
 */

#ifndef SECD_H
#define SECD_H
#include "stack.h"
#include "hash.h"
#include "list.h"
#include "vm.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct _secd_env {
    List* local_table;
    struct _secd_env *up_level;
} tiny_secd_env;



enum opcodes
{
    i_add = 0x01,
    i_sub = 0x02,
    i_div = 0x03,
    i_mul = 0x04,
    i_mod = 0x05,
    i_ld = 0x06,
    i_ldc = 0x0a,
    i_ldf = 0x0e,
    i_ap = 0x0f,
    i_rtn = 0x10,
    i_nil = 0x11,
    i_cons = 0x12,
    i_sel = 0x13,
    i_join = 0x14,
    i_eq = 0x15,
    i_gt = 0x16,
    i_lt = 0x17,
    i_ge = 0x18,
    i_le = 0x19,
    i_def = 0x1a,
    i_stop = 0x1b,
    i_ldn = 0x1c,
    i_ldfn = 0x1d,
    i_dum = 0x1e,
    i_rap = 0x1f,
    i_dap = 0x21,
    i_tap = 0x20
};

typedef struct _bytecode
{
    enum opcodes opcode;
    tiny_value *op;
    union {
        struct{
            int level;
            int pos;
        };
        struct{
            struct _bytecode *branch1;
            struct _bytecode *branch2;
        };
    };
    struct _bytecode *next;
} tiny_bytecode;

typedef struct _secd_dump{
    tiny_bytecode *c;
    Stack *s;
    tiny_secd_env *e;
}tiny_secd_dump;

struct SecdVm
{
    tiny_bytecode *code;
    HMap globalEnv;
    tiny_secd_env *environment;
    Stack *stack;
    Stack *dump;
    void *instructions[512];
    int IP;
    tiny_value NIL;
    tiny_value *objects;
    tiny_value *current;
    int count;
    tiny_value *freelist;
};

typedef void (*ins_func)(struct SecdVm *vm);
typedef void (*c_func)(struct SecdVm *vm, tiny_value *args);
void regist_opcode(struct SecdVm *vm, short opcode, ins_func func);
void regist_global_func(struct SecdVm *vm, char *name, c_func func);
tiny_value *lookup_global(struct SecdVm *vm, char *name);
tiny_value *lookup_local(tiny_secd_env *, int level, int position);
struct SecdVm *make_secd_vm();
void SecdVm_init(struct SecdVm *vm);
void SecdVm_run(struct SecdVm *vm,tiny_bytecode *code);
tiny_bytecode *make_bytecode(enum opcodes);
void display_bytecode(tiny_bytecode *);
tiny_secd_env *make_secd_env(tiny_secd_env *);
tiny_secd_dump *make_secd_dump(tiny_bytecode *c,Stack *s,tiny_secd_env *e);
#ifdef __cplusplus
}
#endif

#endif /* SECD_H */
